#include <errno.h>
#include <linux/sys.h>
#include <string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fork.h>
#include <asm/io.h>
#include <mystdio.h>

#define COUNTER 100

#define LATCH (1193180/HZ)

#include <linux/mm.h>
	
#include <asm/system.h>
	
#define PAGE_SIZE 4096

extern void timer_interrupt();
extern int system_call();

union task_union {
    struct task_struct task;
    char stack[PAGE_SIZE];
};

static union task_union init_task = {INIT_TASK, };

struct task_struct * current = &(init_task.task);
struct task_struct * task[NR_TASKS] = {&(init_task.task), };

int clock = COUNTER;

void do_timer(long cpl) {
    if (clock >0 && clock <= COUNTER) {
        clock--;
        //printm(0, 1024, 768, 50, 10, PURPLE, "%d", clock);
    }
    else if (clock == 0) {
        schedule();
        clock = COUNTER;
    }
    else {
        clock = COUNTER;
    }
}

void schedule0() {
    if (current == task[0] && task[1]) {
    //if (current == task[0] ) {
        //current=task[1];
        switch_to(1);
        printm(0, 1024, 768, 100, 0, WHITE, "BB %d", current);
    }
    else if (current == task[1]) {
        //current=task[0];
        switch_to(0);
        printm(0, 1024, 768, 100, 0, RED, "AA %d", current);
    }
}

void schedule() {
    int i;
    int next = -1;

    // 遍历任务数组，找到第一个可运行的任务
    for (i = 0; i < NR_TASKS; i++) {
        if (task[i] && task[i]->state == TASK_RUNNING && current != task[i]) {
            next = i;
            break;
        }
    }

    if (next >= 0 && current != task[next]) {
        printm(0, 1024, 768, 100, 20, RED, "Current task: %d", current->pid);
        printm(0, 1024, 768, 100, 40, WHITE, "Switching to task: %d", next);
        switch_to(next);
        printm(0, 1024, 768, 100, 0, WHITE, "Switched to task %d", next);
    }
    else{
        printm(0, 1024, 768, 100, 0, WHITE, "Not switched to task %d", next);
    }
}

long user_stack[PAGE_SIZE >> 2];

struct 
{
    long *a;
    short b;
} stack_start = {&user_stack[PAGE_SIZE >> 2], 0x10};

void sched_init() {
    int i;
    struct desc_struct * p;
    set_tss_desc(gdt + FIRST_TSS_ENTRY, &(init_task.task.tss));
    set_ldt_desc(gdt + FIRST_LDT_ENTRY, &(init_task.task.ldt));

    p = gdt+2+FIRST_TSS_ENTRY;

    for(i=1;i<NR_TASKS;i++) {
        task[i] = 0;
        p->a = p->b = 0;
        p++;
        p->a = p->b = 0;
        p++;
    }

    __asm__("pushfl; andl $0xffffbfff, (%esp); popfl");
    ltr(0);
    lldt(0);

    /* open the clock interruption! */
    outb_p(0x36, 0x43);
    outb_p(LATCH & 0xff, 0x40);
    outb(LATCH >> 8, 0x40);
    set_intr_gate(0x20, &timer_interrupt);
    outb(inb_p(0x21) & ~0x01, 0x21);

    set_system_gate(0x80, &system_call);
}

void test_a(void) {
 static int i=0;
 for(;;){
  printm(0, 1024, 768, 80, 0, RED, "A %d", i++);
 }
}

void test_b(void) {
 static int i=0;
 for(;;){
  printm(0, 1024, 768, 85, 0, WHITE, "B %d", i++);
 }
}
